package com.cn.gateway.config;

/**
 * @author zhoujunming
 * @Description TODO
 * @date 2022/6/8 16:31
 * @email zhoujunming@bluemoon.com.cn*/

import com.cn.gateway.handler.CommonAccessDeniedHandler;
import com.cn.gateway.handler.CommonAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
*
 * 资源服务器配置
 * Created by macro on 2020/6/19.
*/


@Configuration
@EnableWebFluxSecurity
@Import({
        //重写401认证失败响应体
        CommonAuthenticationEntryPoint.class,
        //重写403权限不足响应体
        CommonAccessDeniedHandler.class
})
public class ResourceServerConfig {
    @Autowired
    private AuthorizationManagerConfig authorizationManagerConfig;

    @Autowired
    private CommonAuthenticationEntryPoint commonAuthenticationEntryPoint;

    @Autowired
    private CommonAccessDeniedHandler commonAccessDeniedHandler;

    //redis权限列表key
    public final static String RESOURCE_ROLES_MAP = "AUTH:RESOURCE_ROLES_MAP";
    //权限的前置部分
    public final static String AUTHORITY_PREFIX = "ROLE_";

    public final static String AUTHORITY_CLAIM_NAME = "authorities";
    //token标识
    public final static String TOKEN_HEADER = "Authorization";
    //发往其他服务的请求头标识
    public final static String USER_HEADER = "USER_HEADER";

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        List<String> permitAllResouces= new ArrayList<>();
        //Swagger资源
        permitAllResouces.addAll(Arrays.asList("/swagger-ui.html","/doc.html", "/v2/**", "/swagger-resources", "/swagger-resources/**", "/webjars/**","v3/**","favicon.ico","/oauth/**","/rsa/publicKey","/login/**", "/logout/**","/login"));  //"/test/**","/data/**","/oauth/**", "/login/**", "/logout/**",
        String[] resouceArray=permitAllResouces.toArray(new String[]{});

        http.oauth2ResourceServer().jwt()
                .jwtAuthenticationConverter(jwtAuthenticationConverter());
        http.authorizeExchange()
                .pathMatchers(resouceArray).permitAll()//白名单配置
                .anyExchange().access(authorizationManagerConfig)//鉴权管理器配置
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(commonAuthenticationEntryPoint)//处理未认证
                .accessDeniedHandler(commonAccessDeniedHandler)//处理未授权
//                .and().
                .and().csrf().disable();
        return http.build();
    }

  @Bean
    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AUTHORITY_PREFIX);
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AUTHORITY_CLAIM_NAME);
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }
}
